package goroutine

import (
	"time"
)

// 空闲工作协程管理器-栈
type idleMngStack struct {
	// 空闲工作协程列表
	idleList []*worker
}

// 计算空闲工作协程数量
func (s *idleMngStack) Len() int {
	return len(s.idleList)
}

// 检查栈是否为空
func (s *idleMngStack) IsEmpty() bool {
	return s.Len() == 0
}

// 检查栈是否已满
func (s *idleMngStack) IsFull() bool {
	return false
}

// 获取一个空闲工作协程
func (s *idleMngStack) GetWorker() (worker *worker) {
	length := s.Len()
	if length > 0 {
		worker = s.idleList[length-1]
		s.idleList[length-1] = nil
		s.idleList = s.idleList[:length-1]
	}

	return
}

// 放回一个空闲工作协程
func (s *idleMngStack) PutWorker(worker *worker) {
	s.idleList = append(s.idleList, worker)
}

// 清除过期工作协程
func (s *idleMngStack) Expire(duration time.Duration) (list []*worker) {
	length := s.Len()
	if length < 1 {
		return
	}

	startTime := time.Now().Add(-duration)
	index := s.binarySearch(startTime)
	if index > -1 {
		list = append(list, s.idleList[:index+1]...)
		count := copy(s.idleList, s.idleList[index+1:])
		for i := count; i < length; i++ {
			s.idleList[i] = nil
		}
		s.idleList = s.idleList[:count]
	}

	return
}

// 清空队列
func (s *idleMngStack) Clear() (list []*worker) {
	list = append(list, s.idleList...)

	for i := 0; i < s.Len(); i++ {
		s.idleList[i] = nil
	}
	s.idleList = s.idleList[:0]

	return
}

// 查找超时空闲工作协程-二分查找
func (s *idleMngStack) binarySearch(startTime time.Time) int {
	middle, left, right := 0, 0, s.Len()-1
	for left <= right {
		middle = (left + right) / 2
		if s.idleList[middle].idleTime.After(startTime) {
			right = middle - 1
		} else {
			left = middle + 1
		}
	}

	return right
}

// 创建一个空闲工作协程栈
func newIdleMngStack() *idleMngStack {
	stack := new(idleMngStack)
	stack.idleList = make([]*worker, 0)
	return stack
}
